package service.impl;

import dao.GoodsDao;
import dao.UserDao;
import dao.impl.GoodsDaoImpl;
import dao.impl.UserDaoImpl;
import model.Query;
import model.bo.GoodsBO;
import model.bo.ReplyBO;
import model.bo.SpecBO;
import model.bo.TypeBO;
import model.InnerResult;
import model.po.*;
import model.vo.GetGoodsInfoVO;
import model.vo.MessageVO;
import service.GoodsService;
import utils.ModelUtils;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class GoodsServiceImpl implements GoodsService {
    private GoodsDao goodsDao = new GoodsDaoImpl();
    private UserDao userDao = new UserDaoImpl();

    /**
     * 获取系统中全部的商品类别信息
     * @return
     */
    @Override
    public InnerResult getTypes() {
        List<Type> types = goodsDao.getAllTypes();
        return InnerResult.fulfill(types);
    }

    /**
     * 获取某种类别下所有的商品信息
     * @param query
     * @return
     */
    @Override
    public InnerResult getGoodsByType(Query query) {
        TypeBO type = new TypeBO();
        ModelUtils.queryToModel(query, type);

        Type tp = new Type();
        tp.setId(type.getTypeId());
        List<Goods> goodsList = goodsDao.getGoodsByType(tp);
        return InnerResult.fulfill(goodsList);
    }

    /**
     * 添加商品
     * @param goodsBO
     * @return
     */
    @Override
    public InnerResult addGoods(GoodsBO goodsBO) {
        Goods goods = new Goods();
        ModelUtils.copyProperties(goods, goodsBO, Arrays.asList("name", "typeId", "img", "desc"));
        List<SpecBO> specs = goodsBO.getSpecList();
        double price = specs.get(0).getUnitPrice();
        for (int i = specs.size() - 1; i >= 0; i--) {
            double pricei = specs.get(i).getUnitPrice();
            if (price > pricei) {
                price = pricei;
            }
        }
        goods.setPrice(price);
        int result = goodsDao.addGoods(goods);
        if (1 != result) {
            return InnerResult.reject("添加失败");
        }
        int goodsId = goodsDao.lastInsertId();
        if (0 == goodsId) {
            return InnerResult.reject("添加规格失败");
        }
        List<Spec> specList = new ArrayList<>(specs.size());
        for (SpecBO sbo : specs) {
            specList.add(new Spec(goodsId, sbo.getSpecName(), sbo.getStockNum(), sbo.getUnitPrice()));
        }
        result = goodsDao.addSpecs(specList);
        return 0 == result ? InnerResult.reject("添加规格失败") : InnerResult.fulfill("添加成功");
    }

    @Override
    public InnerResult updateGoods(GoodsBO goodsBO, String path) {
        Goods goods = new Goods();
        ModelUtils.copyProperties(goods, goodsBO, Arrays.asList("id", "name", "typeId", "img", "desc"));
        List<SpecBO> specs = goodsBO.getSpecList();
        double price = specs.get(0).getUnitPrice();
        for (int i = specs.size() - 1; i >= 0; i--) {
            double pricei = specs.get(i).getUnitPrice();
            if (price > pricei) {
                price = pricei;
            }
        }
        goods.setPrice(price);
        int result;

        Goods getImg = goodsDao.getGoodsInfo(goods.getId());
        String bfImg = getImg.getImg();
        if (bfImg.equals(goods.getImg())) {
            result = goodsDao.updateGoods(goods);
        } else {
            try {
                Files.deleteIfExists(Paths.get(path + bfImg));
            } catch (IOException e) {
                e.printStackTrace();
            }
            result = goodsDao.updateGoods(goods);
        }

        if (1 != result ) {
            return InnerResult.reject("修改失败");
        }

        List<Spec> specList = new ArrayList<>(specs.size());
        for (SpecBO sbo : specs) {
            specList.add(new Spec(sbo.getSpecName(), sbo.getId(), sbo.getStockNum(), sbo.getUnitPrice()));
        }
        result = goodsDao.updateSpecs(specList);

        List<Spec> specsUptoDate = goodsDao.getSpecs(goodsBO.getId());
        price = Double.MAX_VALUE;
        for (Spec s : specsUptoDate) {
            if (s.getPrice() < price) {
                price = s.getPrice();
            }
        }
        goodsDao.setPrice(goodsBO.getId(), price);

        return 0 == result ? InnerResult.reject("修改规格失败") : InnerResult.fulfill("添加成功");
    }

    @Override
    public InnerResult getGoodsInfo(String id) {
        Goods goods = goodsDao.getGoodsInfo(Integer.valueOf(id));
        if (null == goods) { //不存在该id对应的商品
            return InnerResult.reject("非法参数");
        }
        List<Spec> specList = goodsDao.getSpecs(Integer.valueOf(id));

        GoodsBO goodsBO = new GoodsBO();
        ModelUtils.copyProperties(goodsBO, goods, Arrays.asList("name", "typeId", "img", "desc"));
        List<SpecBO> specs = new ArrayList<>(specList.size());
        for (Spec s : specList) {
            specs.add(new SpecBO(s.getId(), s.getName(), s.getNumber(), s.getPrice()));
        }
        goodsBO.setSpecList(specs);

        GetGoodsInfoVO goodsVO = new GetGoodsInfoVO();
        goodsVO.setGoods(goods);
        goodsVO.setSpecs(specs);
        return InnerResult.fulfill(goodsVO);
    }

    @Override
    public InnerResult addSpec(SpecBO spec) {
        Spec specToDb = new Spec(spec.getGoodsId(), spec.getSpecName(), spec.getStockNum(), spec.getUnitPrice());
        Goods goodsFromDb = goodsDao.getGoodsInfo(spec.getId());
        if (null != goodsFromDb) {
            return InnerResult.reject("分类重复");
        }
        int result = goodsDao.addSpecs(Collections.singletonList(specToDb));
        List<Spec> specs = goodsDao.getSpecs(spec.getGoodsId());
        double price = Double.MAX_VALUE;
        for (Spec s : specs) {
            if (s.getPrice() < price) {
                price = s.getPrice();
            }
        }
        goodsDao.setPrice(spec.getGoodsId(), price);
        return 0 == result ? InnerResult.reject("添加规格失败") : InnerResult.fulfill(spec);
    }

    @Override
    public InnerResult deleteSpec(SpecBO spec) {
        Spec specToDb = new Spec(spec.getGoodsId(), spec.getSpecName());
        int result = goodsDao.deleteSpec(spec);
        return 0 == result ? InnerResult.reject("删除规格失败") : InnerResult.fulfill();
    }

    @Override
    public InnerResult deleteGoods(String id, String path) {
        Integer gid = Integer.valueOf(id);
        Goods goods = goodsDao.getGoodsInfo(gid);
        if (null == goods) { //这里全部都返回成功
            return InnerResult.fulfill();
        }
        String img = goods.getImg();
        try {
            Files.deleteIfExists(Paths.get(path + img));
        } catch (IOException e) {
            e.printStackTrace();
        }
        goodsDao.deleteGoods(gid);
        return InnerResult.fulfill();
    }

    @Override
    public InnerResult repliedMsg() {
        List<Message> messages = goodsDao.repliedMsg();
        List<MessageVO> messageVOS = getMessageVOS(messages);
        return InnerResult.fulfill(messageVOS);
    }

    @Override
    public InnerResult noReplyMsg() {
        List<Message> messages = goodsDao.noReplyMsg();
        List<MessageVO> messageVOS = getMessageVOS(messages);
        return InnerResult.fulfill(messageVOS);
    }

    //Private Methods
    private List<MessageVO> getMessageVOS(List<Message> messages) {
        List<Integer> ids = new ArrayList<>(messages.size());
        for (Message m : messages) {
            ids.add(m.getGoodsId());
        }
        List<String> goodsNames = goodsDao.getGoodsNameByIds(ids);

        int size = ids.size();
        for (int i = 0; i < size; i++) {
            ids.set(i, messages.get(i).getUserId());
        }
        List<String> usersNames = userDao.getUserNameByIds(ids);

        List<MessageVO> messageVOS = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            Message now = messages.get(i);
            messageVOS.add(new MessageVO(
                    now.getId(),
                    now.getUserId(),
                    now.getGoodsId(),
                    now.getContent(),
                    now.getReplyContent(),
                    now.getState(),
                    now.getCreatetime(),
                    new MessageVO.G(goodsNames.get(i)),
                    new MessageVO.U(usersNames.get(i))
            ));
        }
        return messageVOS;
    }

    @Override
    public InnerResult reply(ReplyBO reply) {
        Message msg = new Message();
        msg.setId(reply.getId());
        msg.setReplyContent(reply.getContent());
        msg.setState(0);
        int result = goodsDao.reply(msg);
        return 0 == result ? InnerResult.reject("回复失败") : InnerResult.fulfill();
    }
}
